home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / language / sozobon2.zoo / top / peep1.c < prev    next >
C/C++ Source or Header  |  1990-12-14  |  5KB  |  239 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Tony Andrews
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  */
  11.  
  12. /*
  13.  * Single-instruction peephole optimizations and the overall driver routine.
  14.  */
  15.  
  16. #include "top.h"
  17.  
  18.  
  19. void
  20. peep(bp)
  21. register BLOCK    *bp;
  22. {
  23.     bool    peep1(), peep2(), peep3();
  24.     extern    BLOCK    *fhead;
  25.     register bool    changed;
  26.  
  27.     peep1(bp);
  28.  
  29.     /*
  30.      * Loop until no more changes are made. After each change, do
  31.      * live/dead analysis or the data gets old. In each loop, make
  32.      * at most one change.
  33.      */
  34.     do {
  35.         changed = peep3(bp);
  36.  
  37.         if (!changed)
  38.             changed = peep2(bp);
  39.  
  40.         if (!changed)
  41.             changed = peep1(bp);
  42.  
  43.         rhealth(fhead, FALSE);
  44.  
  45.     } while (changed);
  46. }
  47.  
  48. /*
  49.  * ipeep1(ip) - check for changes to the instruction 'ip'
  50.  */
  51. static    bool
  52. ipeep1(bp, ip)
  53. register BLOCK    *bp;
  54. register INST    *ip;
  55. {
  56.     /*
  57.      * clr.l  Dn            => moveq.l  Dn
  58.      */
  59.     if (ip->opcode == CLR && ip->src.amode == REG &&
  60.         ISD(ip->src.areg) && (ip->flags & LENL)) {
  61.         ip->opcode = MOVEQ;
  62.         ip->dst = ip->src;    /* we'll have two operands now */
  63.         ip->src.amode = IMM;
  64.         ip->src.disp = 0;
  65.         DBG(printf("%d ", __LINE__))
  66.         return TRUE;
  67.     }
  68.  
  69.     /*
  70.      * move.*  #n,Dn        => moveq.l  #n,Dn
  71.      *
  72.      * moveq is always a long operation, but as long as the immediate
  73.      * value is appropriate, we don't care what the original length
  74.      * was. Clearing upper bytes won't matter.
  75.      */
  76.     if (ip->opcode == MOVE && ip->src.amode == IMM && ISD(ip->dst.areg) &&
  77.         D8OK(ip->src.disp)) {
  78.             ip->opcode = MOVEQ;
  79.             ip->flags = LENL;
  80.         DBG(printf("%d ", __LINE__))
  81.             return TRUE;
  82.     }
  83.  
  84.     /*
  85.      * add.x  #n, X         => addq.x  #n, X
  86.      *
  87.      * where 1 <= n <= 8
  88.      */
  89.     if (ip->opcode == ADD && ip->src.amode == IMM &&
  90.         ip->src.disp >= 1 && ip->src.disp <= 8) {
  91.             ip->opcode = ADDQ;
  92.         DBG(printf("%d ", __LINE__))
  93.             return TRUE;
  94.     }
  95.  
  96.     /*
  97.      * sub.x  #n, X         => subq.x  #n, X
  98.      *
  99.      * where 1 <= n <= 8
  100.      */
  101.     if (ip->opcode == SUB && ip->src.amode == IMM &&
  102.         ip->src.disp >= 1 && ip->src.disp <= 8) {
  103.             ip->opcode = SUBQ;
  104.         DBG(printf("%d ", __LINE__))
  105.             return TRUE;
  106.     }
  107.  
  108.     /*
  109.      * movem.x  Reg,-(sp)        => move.x Reg,-(sp)
  110.      */
  111.     if (ip->opcode == MOVEM && ip->src.amode == REG &&
  112.         ip->dst.areg == SP && ip->dst.amode == (REGI|DEC)) {
  113.             ip->opcode = MOVE;
  114.         DBG(printf("%d ", __LINE__))
  115.             return TRUE;
  116.     }
  117.  
  118.     /*
  119.      * movem.x  (sp)+,Reg        => move.x (sp)+,Reg
  120.      */
  121.     if (ip->opcode == MOVEM && ip->dst.amode == REG &&
  122.         ip->src.amode == (REGI|INC) && ip->src.areg == SP) {
  123.             ip->opcode = MOVE;
  124.         DBG(printf("%d ", __LINE__))
  125.             return TRUE;
  126.     }
  127.  
  128.     /*
  129.      *    add[q]    #?, Rn
  130.      *
  131.      * Remove instruction if Rn is dead. This is most often used
  132.      * to eliminate the fixup of SP following a function call when
  133.      * we're just about to return, since the "unlk" clobbers SP
  134.      * anyway.
  135.      */
  136.     if ((ip->opcode == ADDQ || ip->opcode == ADD) && ip->src.amode == IMM &&
  137.          ip->dst.amode == REG) {
  138.  
  139.         if ((ip->live & RM(ip->dst.areg)) == 0) {
  140.                  delinst(bp, ip);
  141.             DBG(printf("%d ", __LINE__))
  142.                  return TRUE;
  143.         }
  144.     }
  145.  
  146.     /*
  147.      *    move.x    X, X
  148.      *
  149.      *    Delete as long as X isn't INC or DEC
  150.      */
  151.     if ((ip->opcode == MOVE) && opeq(&ip->src, &ip->dst) &&
  152.         ((ip->src.amode & (INC|DEC)) == 0)) {
  153.  
  154.         delinst(bp, ip);
  155.         DBG(printf("%d ", __LINE__))
  156.         return TRUE;
  157.     }
  158.  
  159.     /*
  160.      *    move.x    Rm, Rn
  161.      *
  162.      *    Delete if Rn is dead.
  163.      */
  164.     if (ip->opcode == MOVE &&
  165.          ip->src.amode == REG && ip->dst.amode == REG) {
  166.  
  167.         if ((ip->live & RM(ip->dst.areg)) == 0) {
  168.                  delinst(bp, ip);
  169.             DBG(printf("%d ", __LINE__))
  170.                  return TRUE;
  171.         }
  172.     }
  173.  
  174.  
  175.     /*
  176.      *    cmp.x    #0, X        =>    tst.x    X
  177.      *    beq/bne                beq/bne
  178.      *
  179.      *    Where X is not An
  180.      */
  181.     if (bp->last == ip && (bp->bcode == BEQ || bp->bcode == BNE) &&
  182.         ip->opcode == CMP &&
  183.         ((ip->dst.amode != REG) || !ISA(ip->dst.areg))) {
  184.  
  185.         if (ip->src.amode == IMM && ip->src.disp == 0) {
  186.             ip->opcode = TST;
  187.             ip->src = ip->dst;
  188.             ip->dst.amode = NONE;
  189.             DBG(printf("%d ", __LINE__))
  190.             return TRUE;
  191.         }
  192.     }
  193.  
  194.     /*
  195.      * add.x  #n, Am         => lea  n(Am), Am
  196.      *
  197.      * where 'n' is a valid displacement
  198.      */
  199.     if (ip->opcode == ADD && ip->src.amode == IMM && ip->dst.amode == REG &&
  200.         ISA(ip->dst.areg) && DOK(ip->src.disp)) {
  201.             ip->opcode = LEA;
  202.             ip->flags = 0;
  203.             ip->src.amode = REGID;
  204.             ip->src.areg = ip->dst.areg;
  205.         DBG(printf("%d ", __LINE__))
  206.             return TRUE;
  207.     }
  208.  
  209.     return FALSE;
  210. }
  211.  
  212. /*
  213.  * peep1(bp) - peephole optimizations with a window size of 1
  214.  */
  215. static    bool
  216. peep1(bp)
  217. register BLOCK    *bp;
  218. {
  219.     register INST    *ip;
  220.     register bool    changed = FALSE;
  221.     register bool    bchange;
  222.  
  223.     DBG(printf("p1: "))
  224.     for (; bp != NULL ;bp = bp->next) {
  225.         bchange = FALSE;
  226.         for (ip = bp->first; ip != NULL ;ip = ip->next) {
  227.             if (ipeep1(bp, ip)) {
  228.                 s_peep1++;
  229.                 changed = TRUE;
  230.                 bchange = TRUE;
  231.             }
  232.         }
  233.         if (bchange)
  234.             bprep(bp);
  235.     }
  236.     DBG(printf("\n"); fflush(stdout))
  237.     return changed;
  238. }
  239.